// controller project main.go
package main

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"html/template"
	"image/jpeg"
	"log"
	"mustang"
	"mustang/mouse"
	"net/http"
	"net/rpc"
	"os"
	"reflect"

	"github.com/whtang/GoRTP/rtp"
	"golang.org/x/net/websocket"
)

var mouseActions chan *mouse.MouseAction //接收web发送的鼠标动作

//setUpRTP 用来初始化RTP会话
func setUpRTP() (tp *rtp.TransportUDP, rs *rtp.Session) {
	tp, _ = rtp.NewTransportUDP(mustang.Controller, mustang.ControllerPort)
	rs = rtp.NewSession(tp, tp)
	rs.AddRemote(&rtp.Address{mustang.Client.IP, mustang.ClientPort, mustang.ClientPort + 1})
	strControllerIdx, _ := rs.NewSsrcStreamOut(&rtp.Address{mustang.Controller.IP, mustang.ControllerPort, mustang.ControllerPort + 1}, 4030201, 3213)
	rs.SsrcStreamOutForIndex(strControllerIdx).SetPayloadType(0)
	return
}

//ReceivePic 用来接收来自RTP的会话，必须先调用setUpRTP
func ReceivePic() {
	_, rs := setUpRTP()
	rs.StartSession()
	dataReceiver := rs.CreateDataReceiveChan()
	var buf bytes.Buffer
	var picBuf bytes.Buffer
	packet := new(mustang.Packet)
	decoder := gob.NewDecoder(&buf)
	start := false
	log.Println("waiting for packet")
	// !!!!!!!!
	// 这里有问题
	// 如果client先运行会导致接受错误.
	for rp := range dataReceiver {

		if !rp.IsValid() {
			rp.FreePacket()
			continue
		}
		// 调试信息可删除
		log.Println("received one packet, sequence: ", rp.Sequence(), "len: ", len(rp.Payload()), "valid: ", rp.IsValid())
		buf.Write(rp.Payload())
		err := decoder.DecodeValue(reflect.ValueOf(&packet))
		buf.Reset()
		rp.FreePacket()
		if err != nil {
			log.Fatalln(err, ",", buf.Len(), ",", rp.IsValid())
			err = nil
			continue
		}
		if packet.SequenceNumber() == 0 {
			start = true
			log.Println("start make pic")
		} else if packet.SequenceNumber() == packet.Total()-1 && start {
			start = false
			picBuf.Write(packet.Data)
			img, err := jpeg.Decode(&picBuf)
			if err != nil {
				log.Fatalln(err)
			} else {
				f, _ := os.Create("lenna.jpg")
				jpeg.Encode(f, img, &jpeg.Options{25})
				f.Close()
				log.Fatalln("success")
			}
		}
		if start {
			picBuf.Write(packet.Data)
		}
	}
}

//RPCSender 是用来发送鼠标动作的函数, 它一直运行, 使用Channel接收请求
func RPCSender() {
	clientRPC, err := rpc.DialHTTP("tcp", fmt.Sprintf("%s:%d", mustang.Client, mustang.ClientRPCPort))
	if err != nil {
		log.Fatalln("rpc: ", err)
	}
	for action := range mouseActions {
		clientRPC.Call("RPCMouse.RPCPerform", m, blank)
		if err != nil {
			log.Println("rpc: ", err)
		} else {
			log.Println("rpc: S S")
		
	}
}

//MouseServer 用来处理Websocket连接, Websocket连接用于接收来自Web的鼠标键盘动作事件
func MouseServer(ws *websocket.Conn) {
	
	go RPCSender()
	
	blank := new(int)
	for {
		m := new(mouse.MouseAction)
		err = websocket.JSON.Receive(ws, &m)
		if err != nil {
			log.Println("json parse error: ", err)
			continue
		}
		mouseActions <- m
	}
}

//mainPage 用来产生Web页面
func mainPage(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("main.html")
	t.Execute(w, nil)
}

//init 用来初始化程序
func init() {
	mouseActions = make(chan *mouse.MouseAction, 20)
}

func main() {
	go ReceivePic()
	http.HandleFunc("/", mainPage)
	http.Handle("/mouse/", websocket.Handler(MouseServer))
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
	err := http.ListenAndServe(":12345", nil)
	if err != nil {
		log.Fatal("Listen & Server: ", err)
	}
}
